﻿using System;

/*
 * 创建人：Kewin
 * 
 * 时间：2010.6-2010.9
 * 
 * 说明：
 * 
 * 
 * 修改说明：
 * 
 * 
 */


namespace ConsoleTest.ChapterTen
{
    /// <summary>
    /// 
    /// </summary>
    public class TypeSys
    {
        /*C#引用：
         * 
         * 1 引用可以修改，即引用指向的对象可以修改（典型的案例为参数如果为引用类型，使用ref 关键字）
         * 2 引用可以为空，即引用不指向任何对象
         * 3 引用同C++中的引用相同，都可以通过圆点'.'运算符访问公有成员
         * 4 引用无法访问对象的物理空间
         */

        /*为什么会存在装箱和拆箱概念
         * 因为.NET类型系统中，所有的类型都是从System.Object类派生的。作为方法局部变量的值类型的实例是直接存储在线程栈上的
         * 在本线程中使用这些实例无需通过引用。而某些方向需要的参数是引用类型Object类，值类型虽然从Object中派生，但是没有
         * 引用，因此提出装箱概念以便通过引用方式操作值类型实例。
         */

        /*相等的等价、恒等
         * 
         * 等价的概念指：内部的值相等；
         * 恒等：引用相同；
         */

        /*静态分配与动态分配
         * C#中的对象的内存分配模式取决于对象的实现方式即：值类型还是引用类型
         * 引用类型内存分配与堆上。值类型一般位于线程栈上，可以位于进程堆上。
         */

        /*类型计算中的一个错误
         * 
         * int类型的最大值为22亿以下，如下代码
         * int i=10 0000 0000;
         * long j=i*10;
         * 计算的结果应该是100亿才对，但是上述计算是基于int类型进行的，int类型最大值被限制在20亿以下
         * 
         * 测试代码见：public static void CalcTest()
         */

        /*类与结构体区别
         * 1 类为引用类型，结构为值类型，以及由此而来的一切区别
         * 2 结构不能继承自其他的类或者结构，也不能作为其他类或者结构的基类，即使所有结构都派生在Object类
         * 3 与类的字段不同，结构的字段不能够在声明时初始化
         * 4 开发人员不能够定义结构的默认构造函数，即不带参数的构造函数
         * 5 结构的实例常常存在于栈中，因为栈的大小一般为1M，因此结构不宜太大，太大的结构可以使用类代替
         */

        private class TypeRef { public int state;}
        private struct TypeVal { public int state;}
        /// <summary>
        /// 对于bool型的参数输出是否相等信息
        /// </summary>
        private static void MyAssert(bool Result)
        {
            if (Result)
                System.Console.WriteLine("1");
            else
                System.Console.WriteLine("0");
        }
        /// <summary>
        /// 恒等与等价对比
        /// </summary>
        public static void Equal()
        {
            TypeRef ref1 = new TypeRef();
            TypeRef ref2 = new TypeRef();
            ref1.state = 3;
            ref2.state = 3;


            MyAssert(ref1 != ref2);//不相等
            MyAssert(!ref1.Equals(ref2));//不相等
            MyAssert(!object.ReferenceEquals(ref1, ref2));//不相等

            ref2 = ref1;//修改后，引用相同
            MyAssert(ref1 != ref2);
            MyAssert(!ref1.Equals(ref2));
            MyAssert(!object.ReferenceEquals(ref1, ref2));


            
            TypeVal val1 = new TypeVal();
            TypeVal val2 = new TypeVal();
            val1.state = 3;
            val2.state = 3;
            MyAssert(val1.Equals(val2));//引用相等当且仅当他们引用同一个对象。
            //值类型的Equal方法的默认实现是通过反射机制对实例的各个字段逐一比较
            //即：值类型的实例相等当且仅当他们的所有对应字段的值均相等
            val1.state = 4;
            MyAssert(!val1.Equals(val2));
        }

        /// <summary>
        /// 运算错误问题
        /// </summary>
        public static void CalcTest()
        {
            int i = 1000000000;
            //checked//checked检查它作用的域中可能出现的违例，并抛出一个异常；而unchecked则阻止所有的检查。
            //{
            //    long j = i * 10;
            //    System.Console.WriteLine("int max value is :" + int.MaxValue);
            //    System.Console.WriteLine(j);
            //}

            long j = i * 10;
            System.Console.WriteLine("int max value is :" + int.MaxValue);
            System.Console.WriteLine(j);
        }

        /// <summary>
        /// 位域所在字节大小测试
        /// </summary>
        public static void BitFlags()
        {
            System.Console.WriteLine(sizeof(Flags));
        }

        /// <summary>
        /// 字符串格式化输出
        /// </summary>
        public static void StrFormat()
        {
            int i = 123;
            float f = 3.1415f;

            System.Console.WriteLine("ab{0,-6}cd", i);//占六个字符宽度的左对齐形式，不够的话用空格代替
            System.Console.WriteLine("ab{0:0000}cd", i);//最少四位数字，用0填充
            System.Console.WriteLine("ab{0,6:0000}cd", i);//表示为六个字符宽度的右对齐形式，显示最少四位数字，用0填充

            System.Console.WriteLine("ab{0:####}cd", i);//
            System.Console.WriteLine("ab{0:##}cd", i);//
            System.Console.WriteLine("ab{0:##.##}cd", f);//最多显示两位小数

            System.Console.WriteLine("ab{0:##.#}cd", 3.14);//小数舍
            System.Console.WriteLine("ab{0:##.#}cd", 3.18);//小数入
            System.Console.WriteLine("ab{0:##%}cd", 0.143);//0.413先乘以100然后舍去多余小数，变为百分比形式

            System.Console.WriteLine("ab{0:E}cd", f);//科学计数法
            System.Console.WriteLine("ab{0:X}cd", i);//十六进制大写字母表示
            System.Console.WriteLine("ab{0:x}cd", i);//十六进制小写字母表示
        }
    }

    /// <summary>
    /// 位域
    /// </summary>
    [System.Flags()]
    public enum Flags : byte
    {
        Flag1 = 0x01,//16进制表示的位域
        Flag2 = 0x02,//
        Flag3 = 0x04,//
        Flag4 = 0x08,//
        Flag5 = 0x10,//
        Flag6 = 0x20,//
        Flag7 = 0x40,//
        Flag8 = 0x80,//
    }
}